package com.example.security_demo.filter;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 如何禁用默认的认证方式
 * 自定义 filter 并且配置到 spring security filter chain 中
 * RequestBody header parameter
 * @author zzh
 * @date 2022/4/16
 * @since 1.0
 */
@RequiredArgsConstructor
@Slf4j
public class SpringSecurityTestFilter extends OncePerRequestFilter {

    private final ObjectMapper objectMapper = new ObjectMapper();

    private final static String POST_METHOD = "POST";


    private final static String DEFAULT_METHOD_URI = "/sms/login";

    private final String uri;

    private AuthenticationFailureHandler failureHandler;


    public SpringSecurityTestFilter(AuthenticationFailureHandler failureHandler) {
        this(failureHandler, DEFAULT_METHOD_URI);
    }

    public SpringSecurityTestFilter(AuthenticationFailureHandler failureHandler, String uri) {
        this.failureHandler = failureHandler;
        this.uri = uri;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        try {
            log.info("uri is {}", request.getRequestURI());
            long startTime = System.currentTimeMillis();
            if (!request.getMethod().equals(POST_METHOD) || !request.getRequestURI().equals(uri)) {
                throw new UsernameNotFoundException("调用方式不匹配");
            }
            JsonNode jsonNode = objectMapper.readTree(request.getInputStream());

            String code =attachBodyContent(jsonNode);
            System.out.println("code is : " + code + " length:"+ code.length());
            filterChain.doFilter(request, response);
            log.info("{} const time {} ms", request.getRequestURI(), System.currentTimeMillis() - startTime);

        } catch (AuthenticationException exception) {
            log.info("exception class is {}", exception.getClass());
            log.info("exception message is {}", exception.getMessage());
            failureHandler.onAuthenticationFailure(request, response, exception);
        }

    }

    private String attachBodyContent(JsonNode jsonNode) {
        if (jsonNode == null) {
            throw new UsernameNotFoundException("无法获取对应参数");
        }
        JsonNode node = jsonNode.get("smsCode");
        if (node == null) {
            throw new UsernameNotFoundException("无法获取对应参数");
        }
        return node.asText();
    }
}
